/*
 * Copyright 2009-2010 the original author or authors.
 *
 * Licensed under the Apache license, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.internna.iwebjtracker.model;

import java.util.Date;
import java.util.Locale;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Temporal;
import javax.persistence.ManyToOne;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQuery;
import javax.persistence.PrePersist;
import javax.persistence.TemporalType;
import org.hibernate.validator.NotNull;
import org.hibernate.validator.NotEmpty;
import org.internna.iwebjtracker.issue.model.Comment;
import org.internna.iwebmvc.model.AbstractDomainEntity;
import org.directwebremoting.annotations.RemoteProperty;
import org.directwebremoting.annotations.DataTransferObject;

/**
 * Comments made by a user regarding some issue.
 *
 * @author Jose Noheda
 * @since 1.0
 */
@Entity
@Table(name = "COMMENTS")
@DataTransferObject(javascript = "IssueComment")
@NamedQuery(name = "IssueComment.findAll", query = "SELECT i FROM IssueComment i")
public class IssueComment extends AbstractDomainEntity implements Comment<TrackerUser, IssueComment, DefaultIssue>, Comparable<IssueComment> {

    private static final long serialVersionUID = -3782911220172027358L;

    @Lob
    @NotEmpty
    @RemoteProperty
    @Column(name = "COMMENT")
    private String comment;

    @NotNull
    @ManyToOne
    @RemoteProperty
    @JoinColumn(name = "ISSUE")
    private DefaultIssue issue;

    @ManyToOne
    @RemoteProperty
    @JoinColumn(name = "PARENT_COMMENT")
    private IssueComment responseTo;

    @NotNull
    @RemoteProperty
    @Column(name = "CREATION")
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;

    @NotNull
    @ManyToOne
    @RemoteProperty
    @JoinColumn(name = "AUTHOR")
    private TrackerUser author;

    /**
     * Logged in user that sent the comment.
     *
     * @return any
     */
    @Override public TrackerUser getAuthor() {
        return author;
    }

    /**
     * Accessor method.
     *
     * @param author a non null instance
     */
    @Override public void setAuthor(TrackerUser author) {
        this.author = author;
    }

    /**
     * Clarifications made by a user.
     *
     * @return any
     */
    public String getComment() {
        return comment;
    }

    /**
     * Accessor method.
     *
     * @param comment a non empty string
     */
    public void setComment(String comment) {
        this.comment = comment;
    }

    /**
     * Date of the first persistent operation on this comment.
     *
     * @return any
     */
    public Date getCreationDate() {
        return creationDate == null ? null : new Date(creationDate.getTime());
    }

    /**
     * Accessor method.
     *
     * @param creationDate a non null date
     */
    protected void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    /**
     * Issue affected.
     *
     * @return any
     */
    @Override public DefaultIssue getIssue() {
        return issue;
    }

    /**
     * Accessor method.
     *
     * @param issue a non null issue
     */
    @Override public void setIssue(DefaultIssue issue) {
        this.issue = issue;
        if (issue != null) {
            issue.addComment(this);
        }
    }

    /**
     * Comment to which this comment is a follow up.
     *
     * @return any
     */
    public IssueComment getResponseTo() {
        return responseTo;
    }

    /**
     * Accessor method.
     *
     * @param responseTo any
     */
    public void setResponseTo(IssueComment responseTo) {
        this.responseTo = responseTo;
    }

    /**
     * Allows comparisons between two comments. Basically comments are ordered
     * by date of creation.
     *
     * @param comment any
     * @return -1 if this date is null or the result of the date comparation
     */
    @Override public int compareTo(IssueComment comment) {
        int comparison = creationDate == null ? -1 : 1;
        if ((comparison == 1) && (comment != null)) {
            comparison = creationDate.compareTo(comment.creationDate);
        }
        return comparison;
    }

    /**
     * Delegates to getComment().
     *
     * @param locale any
     * @return any
     */
    @Override public final String getCaption(Locale locale) {
        return getComment();
    }

    /**
     * Invoked by the persistence provider to add default values.
     * Avoid calling this method.
     */
    @PrePersist
    protected final void prePersist() {
        setCreationDate(new Date());
    }

}
